﻿using System;
using System.IO;
using __ts.Core.Log;

namespace __ts.Core.Plugin
{
    /// <summary>
    /// 
    /// </summary>
    public class PluginDomain
    {
        private AppDomain appDomain;
        private IPlugin _plugin = null;

        /// <summary>
        /// 插件文件路径
        /// </summary>
        private string AssemblyPath { get; set; }
        /// <summary>
        /// 获取插件实例
        /// </summary>
        /// <returns></returns>
        public IPlugin GetPlugin()
        {
            if (_plugin == null)
            {
                RemoteLoader remObj = (RemoteLoader)this.appDomain.CreateInstanceAndUnwrap("__ts.Core", "__ts.Core.Plugin.RemoteLoader");
                _plugin = remObj.Install(this.AssemblyPath);
            }
            return _plugin;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblyPath"></param>
        public PluginDomain(string assemblyPath)
        {
            this.AssemblyPath = assemblyPath;

            if (appDomain == null)
                this.appDomain = CreateAppDomain(assemblyPath);
        }
        /// <summary>
        /// 卸载程序域
        /// </summary>
        public void Unload()
        {
            if (this.appDomain == null)
                return;

            // 从插件列表中移除
            PluginManager.GetInstance.Plugins.Remove(this._plugin.Key);
            // 删除插件文件
            string filePath = PluginManager.GetInstance.PluginsDirectory + "\\" + this._plugin.Name + ".dll";
            if (File.Exists(filePath))
            {
                FileInfo info = new FileInfo(filePath);
                if (info != null)
                {
                    if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                    {
                        info.Attributes &= ~FileAttributes.ReadOnly;
                    }
                    info.Delete();
                }
            }
            // 卸载程序域
            string dn = this.appDomain.FriendlyName;
            AppDomain.Unload(this.appDomain);
            this.appDomain = null;

            Logger.Write(string.Format("卸载程序域{0}。", dn));
        }
        /// <summary>
        /// 创建程序域
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <returns></returns>
        private AppDomain CreateAppDomain(string assemblyPath)
        {
            string filename = Path.GetFileNameWithoutExtension(assemblyPath);
            try
            {
                AppDomainSetup setup = new AppDomainSetup();
                setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
                setup.ApplicationName = "Plugins_" + filename;
                setup.ShadowCopyFiles = "true";
                setup.ShadowCopyDirectories = Path.GetDirectoryName(assemblyPath);
                this.appDomain = AppDomain.CreateDomain("PluginDomain_" + filename, null, setup);

                Logger.Write(string.Format("创建了程序域{0}。", this.appDomain.FriendlyName));
            }
            catch (Exception ex)
            {
                Logger.Write("创建程序域失败：" + ex.Message);
            }
            return this.appDomain;
        }
    }
}
